package com.by.toolkit.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author hjdong@mmears.com
 * Date: 2018/4/19
 * Time: 17:29
 */
@Slf4j
public final class OkHttpUtil {

    public static final int OK = 200;

    private OkHttpUtil() {

    }

    private static OkHttpClient client = new OkHttpClient.
            Builder()
            .connectTimeout(1, TimeUnit.SECONDS)
            .readTimeout(1, TimeUnit.SECONDS)
            .writeTimeout(1, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .addNetworkInterceptor(chain -> chain.proceed(chain.request()))
            .build();

    public static OkHttpClient getInstance() {
        return client;
    }

    public static <T> T post(String url, Map<String, String> reqeustMap, Map<String, Object> bodyMap, Map<String, String> header, Class<T> clazz, OkHttpClient client) throws IOException {

        T t = null;
        url = getQueryString(url, reqeustMap);
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, JSON.toJSONString(bodyMap));
        Request.Builder builder = new Request.Builder();
        builder.url(url).post(body);
        if (Objects.nonNull(header)) {
            header.forEach(builder::addHeader);
        }
        Request request = builder.build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                if (clazz.equals(String.class)) {
                    return (T)result;
                }
                t = JSON.parseObject(result, clazz);
            } else {
                log.warn("[OkHttpUtil][post] 响应码异常:{}", response.code());
            }
        } catch (IOException e) {
            log.info("请求异常:{}", ExceptionUtils.getStackTrace(e));
            throw e;
        }
        return t;
    }

    public static String getQueryString(String url, Map<String, String> queries) {
        StringBuffer sb = new StringBuffer(url);
        if (CollectionUtil.isNotEmpty(queries)) {
            boolean firstFlag = true;
            Iterator iterator = queries.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry<String, String>) iterator.next();
                if (firstFlag) {
                    sb.append("?" + entry.getKey() + "=" + entry.getValue());
                    firstFlag = false;
                } else {
                    sb.append("&" + entry.getKey() + "=" + entry.getValue());
                }
            }
        }
        return sb.toString();
    }

    public static <T> T get(String url, OkHttpClient client, Class<T> reponseClazz) {

        T t = null;
        Request request = new Request.Builder().get().url(url).build();
        try {
            client = ObjectUtil.defaultIfNull(client, getInstance());

            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, reponseClazz);
            } else {
                log.warn("[OkHttpUtil][post] 响应码异常:{}", response.code());
            }
        } catch (IOException e) {
            log.error("请求异常:{}", ExceptionUtils.getStackTrace(e));
            ExceptionUtil.throwError(e.getMessage());
        }
        return t;
    }

    public static Response get(String url) {

        Request request = new Request.Builder().get().url(url).build();
        try {
            client = ObjectUtil.defaultIfNull(client, getInstance());

            Response response = client.newCall(request).execute();
            return response;
        } catch (IOException e) {
            log.error("请求异常:{}", ExceptionUtils.getStackTrace(e));
            ExceptionUtil.throwError(e.getMessage());
        }
        return null;
    }
}
